package site.xuqing.autohelperengine.util;

import android.text.TextUtils;
import android.util.Log;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Calendar;

import site.xuqing.autohelperengine.constant.Constant;

public class LogUtil {

	private final static String LOG_TAG = "LogUtil";

	/** 默认java的文件后缀名 */
	public final static String STR_DEFAULT_JAVA_FILE_EXT = ".java";

	/** 空字符 */
	public final static String STR_EMPTY_STRING = "";

	/** 日志级别 */
	private static LogLevelType m_typeLogLevel = LogLevelType.TYPE_LOG_LEVEL_DEBUG;

	
	static {
		if (Constant.SHOW_LOG) {
			setLogLevel(LogLevelType.TYPE_LOG_LEVEL_DEBUG);
		} else {
			setLogLevel(LogLevelType.TYPE_LOG_LEVEL_ERROR);
		}
	}

	public enum LogLevelType {
		/** 调试类型日志 */
		TYPE_LOG_LEVEL_DEBUG(1),
		/** 关键信息类型日志 */
		TYPE_LOG_LEVEL_INFO(2),
		/** 警告类型日志 */
		TYPE_LOG_LEVEL_WARNING(3),
		/** 错误类型日志 */
		TYPE_LOG_LEVEL_ERROR(4);

		/**
		 * 构造函数,初始化枚举元素值
		 * 
		 * @param iValue
		 *            输入整数值
		 */
		LogLevelType(int iValue) {
			this.m_iEnumValue = iValue;
		}

		/**
		 * 获取枚举型对应的整数值
		 * <p>
		 * Description: 获取枚举型对应的整数值
		 * <p>
		 * 
		 * @date 2013-4-19
		 * @return int型，该枚举元素对应的值
		 */
		public int getValue() {
			return m_iEnumValue;
		}

		/** 枚举元素对应的整数值 */
		private final int m_iEnumValue;
	}

	/**
	 * 不允许创建实例，隐藏构造函数
	 */
	private LogUtil() {

	}


	/**
	 * 
	 * 设置当前日志级别，详见LogLevelType
	 * 
	 * @date 2013-4-19
	 * @param typeLevel
	 *            日志级别
	 */
	public static void setLogLevel(LogLevelType typeLevel) {
		Log.d(LOG_TAG, "typeLevel=" + typeLevel);
		m_typeLogLevel = typeLevel;
	}

	/**
	 * 
	 * 获取当前日志级别
	 * 
	 * @date 2013-4-19
	 */
	public static LogLevelType getLogLevel() {
		return m_typeLogLevel;
	}

	/**
	 * 格式化日志输出，如Login 2013-04-19 14:32:15.042 F[ZWoReaderActivity] L[52]
	 * [onCreate] onCreate start
	 * 
	 * @date 2013-4-19
	 * @param strLevel
	 *            日志级别
	 * @param strModuleName
	 *            模块名称描述
	 * @param strInfo
	 *            日志信息
	 * @param strLineInfo
	 *            行、文件名、方法名信息
	 */
	private static String formatLogString(String strLevel,
                                          String strModuleName, String strInfo, String strLineInfo) {

		if (null == strModuleName || null == strInfo || null == strLineInfo) {
			return null;
		}

		// 日志格式：[D][Login][2013-04-19
		// 14:32:15.042]L[52][ZWoReaderActivity.java][onCreate] onCreate start
		String strReturnInfo = null;

		strReturnInfo = String.format("[%s][%20s][%-24s]%s%s", strLevel,
				strModuleName, Calendar.getInstance().getTime().toLocaleString(),
				strLineInfo, strInfo);
		return strReturnInfo;
		// return String.format("%23s", TimeUtil.getFormattedLocalTimeStr());

	}

	/**
	 * 格式化日志输出，如2013-04-19 14:32:15.042 F[ZWoReaderActivity] L[52] [onCreate]
	 * onCreate start
	 * 
	 * @date 2012-2-28
	 * @param strInfo
	 *            日志信息
	 * @param strLineInfo
	 *            行、文件名、方法名信息
	 */
	public static String formatDateString(String strInfo, String strLineInfo) {
		if (null == strInfo || null == strLineInfo) {
			return null;
		}

		// 日志格式：Login 2013-04-19 14:32:15.042
		// L[52][ZWoReaderActivity.java][onCreate] onCreate start

		String strReturnInfo = null;

		try {
			strReturnInfo = String.format("%-23s%s%s", Calendar.getInstance().getTime()
					.toLocaleString(), strLineInfo, strInfo);
		} catch (Exception e) {
			strReturnInfo = " " + e.getMessage();
		}

		return strReturnInfo;

	}




	/**
	 * 打印调试日志
	 * 
	 * @date 2013-4-19
	 * @param strModuleName
	 *            模块名称描述
	 * @param strInfo
	 *            日志信息
	 */
	public static void d(String strModuleName, String strInfo) {
		// 只有调试级别的日志才打
		if (LogLevelType.TYPE_LOG_LEVEL_DEBUG != m_typeLogLevel) {
			return;
		}

		// 模块名和内容不能为空
		if (TextUtils.isEmpty(strModuleName)
				|| TextUtils.isEmpty(strInfo)) {
			return;
		}

		// 日志格式：Login 2013-04-19 14:32:15.042
		// L[52][ZWoReaderActivity.java][onCreate] onCreate start

		// Debug版本将日志写入文件，release版本将日志输出到LogCat
		Log.d(strModuleName,
				formatDateString(strInfo, getLineInfo(new Throwable())));
	}

	/**
	 * 打印警告日志
	 * 
	 * @date 2013-4-19
	 * @param strModuleName
	 *            模块名称描述
	 * @param strInfo
	 *            日志信息
	 */
	public static void w(String strModuleName, String strInfo) {
		// Err级别时的日志不打印
		if (LogLevelType.TYPE_LOG_LEVEL_ERROR == m_typeLogLevel) {
			return;
		}

		// 模块名和内容不能为空
		if (TextUtils.isEmpty(strModuleName)
				|| TextUtils.isEmpty(strInfo)) {
			return;
		}

		// 日志格式：Login 2013-04-19 14:32:15.042
		// L[62][ZWoReaderActivity.java][onCreate] onCreate finish
		// Debug版本将日志写入文件，release版本将日志输出到LogCat
		Log.w(strModuleName,
				formatDateString(strInfo, getLineInfo(new Throwable())));
	}

	/**
	 * 打印错误日志
	 * 
	 * @date 2013-4-19
	 * @param strModuleName
	 *            模块名称描述
	 * @param strInfo
	 *            日志信息
	 */
	public static void e(String strModuleName, String strInfo) {
		// 模块名和内容不能为空
		if (TextUtils.isEmpty(strModuleName)
				|| TextUtils.isEmpty(strInfo)) {
			return;
		}

		// 日志格式：Login 2013-04-19 14:32:15.042
		// L[63][ZWoReaderActivity.java][onCreate] onCreate finish
		// Debug版本将日志写入文件，release版本将日志输出到LogCat
		Log.e(strModuleName,
				formatDateString(strInfo, getLineInfo(new Throwable())));
	}

	/**
	 * 打印提示日志
	 * 
	 * @date 2013-4-19
	 * @param strModuleName
	 *            模块名称描述
	 * @param strInfo
	 *            日志信息
	 */
	public static void i(String strModuleName, String strInfo) {
		// Err\Warn级别时的日志不打印
		if (LogLevelType.TYPE_LOG_LEVEL_ERROR == m_typeLogLevel
				|| LogLevelType.TYPE_LOG_LEVEL_WARNING == m_typeLogLevel) {
			return;
		}
		// 模块名和内容不能为空
		if (TextUtils.isEmpty(strModuleName)
				|| TextUtils.isEmpty(strInfo)) {
			return;
		}

		// 日志格式：Login 2013-04-19 14:32:15.042
		// L[64][ZWoReaderActivity.java][onCreate] onCreate finish
		// Debug版本将日志写入文件，release版本将日志输出到LogCat
		Log.i(strModuleName,
				formatDateString(strInfo, getLineInfo(new Throwable())));

	}

	public static void i1(String tag, String msg) {  //信息太长,分段打印
		//因为String的length是字符数量不是字节数量所以为了防止中文字符过多，
		//  把4*1024的MAX字节打印长度改为2001字符数
		int max_str_length = 2001 - tag.length();
		//大于4000时
		while (msg.length() > max_str_length) {
			Log.i(tag, msg.substring(0, max_str_length));
			msg = msg.substring(max_str_length);
		}
		//剩余部分
		Log.i(tag, msg);
	}

	/**
	 * 获取代码行的信息，包括文件名、行号、函数名等信息
	 * 
	 * @date 2013-4-19
	 * @param ta
	 *            Throwable对象
	 * @return String类型，包含格式化的文件名、行号、函数名。
	 */
	public static String getLineInfo(Throwable ta) {
		if (null == ta) {
			return null;
		}

		// 行号
		String strLineNumber = null;
		String strFileName = null;
		String strFileNamePostfix = null;
		String strMethodName = null;

		// 获得格式字符串-行号、文件名、格式字符串-方法名
		StackTraceElement[] stackTraceElement = ta.getStackTrace();
		if (null != stackTraceElement && stackTraceElement.length > 1) {
			int iLineNumberTemp = -1;
			iLineNumberTemp = stackTraceElement[1].getLineNumber();

			if (-1 == iLineNumberTemp) {
				Log.w(LOG_TAG, "iLineNumberTemp = " + iLineNumberTemp);
				return STR_EMPTY_STRING;
			} else {
				strLineNumber = String.format("L[%d]", iLineNumberTemp);
			}

			String strFileNameTemp = stackTraceElement[1].getFileName();
			if (TextUtils.isEmpty(strFileNameTemp)) {
				Log.w(LOG_TAG, "strFileNameTemp = " + strFileNameTemp);
				return STR_EMPTY_STRING;
			} else {
				strFileName = strFileNameTemp;
			}

			String strMethodNameTemp = stackTraceElement[1].getMethodName();
			if (TextUtils.isEmpty(strMethodNameTemp)) {
				Log.w(LOG_TAG, "strMethodNameTemp = " + strMethodNameTemp);
				return STR_EMPTY_STRING;
			} else {
				strMethodName = strMethodNameTemp;
			}

			// 若文件名以.java为后缀，则去除后缀
			if (strFileName.substring(
					strFileName.length() - STR_DEFAULT_JAVA_FILE_EXT.length(),
					strFileName.length()).equalsIgnoreCase(
					STR_DEFAULT_JAVA_FILE_EXT)) {
				strFileNamePostfix = strFileName.substring(
						0,
						strFileName.length()
								- STR_DEFAULT_JAVA_FILE_EXT.length());
			} else {
				strFileNamePostfix = strFileName;
			}

			// 格式化文件名字符串
			// strFileName = null;
			strFileName = String.format("F[%s]", strFileNamePostfix);

			// 返回值："F[ZWoReaderActivity]   L[51]  [onCreate]           "
			return String.format("%-23s%-7s%-22s", strFileName, strLineNumber,
					strMethodName);
		} else {
			Log.w(LOG_TAG, "stackTraceElement = " + stackTraceElement);
			return STR_EMPTY_STRING;
		}
	}


	public static String getStackTrace(Exception e) {
		StringWriter sw = new StringWriter();
		PrintWriter pw = new PrintWriter(sw, true);
		e.printStackTrace(pw);
		pw.flush();
		sw.flush();
		String ret = sw.toString();
		try {
			sw.close();
			pw.close();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		return ret;
	}
}
